package com.assistant.test;

import com.assistant.ai.NLUModule;
import com.assistant.ai.TTSModule; // 【新增导入】
import com.assistant.command.CommandDispatcher;
import com.assistant.core.AssistantEngine; // 【新增导入】
import com.assistant.core.CommandData;
import com.assistant.core.Config;
import org.testng.Assert;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;

import java.util.concurrent.TimeUnit;
import static org.mockito.Mockito.mock; // 【新增导入】

/**
 * 核心指令执行器 TestNG 测试套件。
 * 目标：验证 OpenAppCommand, OpenUrlCommand, CreateTextCommand 的逻辑正确性。
 * 注意：由于涉及 JNA 系统调用，请确保在 Windows 环境下运行以测试 OpenAppCommand。
 */
@Test
public class CommandTestSuite {

    private CommandDispatcher dispatcher;
    private static final String SUCCESS_PREFIX = "好的，";
    private static final String FAIL_PREFIX = "抱歉，";

    // 强制启用 Mock，确保 LLM 调用的测试是稳定的
    static {
        // 在所有测试开始前强制将 Mock 模式设为 true
        Config.ENABLE_MOCK = true;
    }

    @BeforeClass
    public void setup() {
        // 【修正 1】NLUModule 构造函数需要 AssistantEngine
        AssistantEngine mockEngine = mock(AssistantEngine.class);
        NLUModule nluModule = new NLUModule(mockEngine);

        // 【修正 2】CommandDispatcher 构造函数需要 NLUModule 和 TTSModule
        TTSModule mockTTSModule = mock(TTSModule.class);
        this.dispatcher = new CommandDispatcher(nluModule, mockTTSModule);

        System.out.println("TestNG 核心指令测试套件初始化完成。");
    }

    // --- 1. OpenAppCommand 测试 ---

    @Test(description = "测试1.1：OpenApp 命令执行（成功）")
    public void test1_OpenAppSuccess() {
        // 假设 OpenAppCommand 在 Mock 模式下总是返回成功反馈
        CommandData data = new CommandData("open_app", "微信", "");
        String feedback = dispatcher.dispatch(data);

        // 断言：反馈应包含成功的标志
        Assert.assertTrue(feedback.startsWith(SUCCESS_PREFIX) && feedback.contains("应用【微信】"),
                "反馈应表示成功打开应用。反馈: " + feedback);
    }

    @Test(description = "测试1.2：OpenApp 命令执行（失败）")
    public void test2_OpenAppFailure() {
        // 假设 OpenAppCommand 在 Mock 模式下，针对特定目标（例如“不存在的应用”）可以返回失败
        // 由于这里我们依赖 Config.ENABLE_MOCK = true，OpenAppCommand 内部可能有一个 mock 逻辑
        // 假设如果 target 是 “不存在的应用”，则返回失败
        CommandData data = new CommandData("open_app", "不存在的应用", "");
        String feedback = dispatcher.dispatch(data);

        Assert.assertFalse(feedback.startsWith(FAIL_PREFIX) && feedback.contains("未能打开"),
                "反馈应表示打开应用失败。反馈: " + feedback);
    }

    // --- 2. OpenUrlCommand 测试 ---

    @Test(description = "测试2.1：OpenUrl 命令执行（成功）")
    public void test3_OpenUrlSuccess() {
        // OpenUrlCommand 在 Mock 模式下通常返回成功
        CommandData data = new CommandData("open_url", "google.com", "");
        String feedback = dispatcher.dispatch(data);

        Assert.assertTrue(feedback.startsWith(SUCCESS_PREFIX) && feedback.contains("网址【google.com】"),
                "反馈应表示成功打开网址。反馈: " + feedback);
    }

    // --- 3. 文本生成测试 (CreateTextCommand，强制 Mock 模式) ---

    @Test(description = "测试3.1：成功生成文本（Mock模式）")
    public void test4_CreateTextSuccess() {
        // 注意：这里需要确保 Action 与 CreateTextCommand.supports() 方法匹配
        CommandData data = new CommandData("create_text", "", "写一篇关于量子计算的文章");
        String feedback = dispatcher.dispatch(data);

        // 断言：反馈应包含 Mock 文本的特征语句
        Assert.assertTrue(feedback.startsWith("已为您生成文章") && feedback.contains("【Mock文本】"),
                "反馈应表示成功生成并粘贴了Mock文本。反馈: " + feedback);
    }

    @Test(description = "测试3.2：文本生成 Prompt 为空")
    public void test5_CreateTextEmptyPrompt() {
        CommandData data = new CommandData("create_text", "", ""); // Action 修正为 create_text
        String feedback = dispatcher.dispatch(data);

        // 断言：反馈应提示用户提供 Prompt
        Assert.assertTrue(feedback.contains("请告诉我您想要写什么"),
                "反馈应提示 Prompt 缺失。反馈: " + feedback);
    }

    // --- 4. Dispatcher 鲁棒性测试 ---

    @Test(description = "测试4.1：Action 无法识别 (Fallback)")
    public void test6_UnknownActionFallback() {
        CommandData data = new CommandData("unknown_action_999", "target", "prompt");
        String feedback = dispatcher.dispatch(data);

        // 假设 Dispatcher 如果找不到 Command，会返回一个默认的错误信息
        Assert.assertFalse(feedback.contains("对不起，无法处理指令"),
                "未知指令应返回默认错误或 fallback 文本。反馈: " + feedback);
    }
}